
#define GLFW_INCLUDE_VULKAN
#include "gfx-mgr.h"
#include "../utils/time.h"
#include "gfx-texture.h"

#include "../window/window-mgr.h"

// 校验层
const bool enableValidationLayers = true;
std::vector<const char *> ValidationLayers = {"VK_LAYER_KHRONOS_validation"};
std::vector<const char *> DeviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};

GfxMgr *GfxMgr::getInstance()
{
    static GfxMgr _instance;
    return &_instance;
}

GfxMgr::GfxMgr()
{
}

void GfxMgr::init()
{
    this->_createInstance();
    this->_setupDebugMessenger();
    this->_createSurface();
    this->_initPhysicalDevice();
    this->_createLogicalDevice();
    this->_createSwapChain();
    this->_createImageViews();
    this->_createCommandPool();
    this->_createDescriptorPool();
    this->_createSyncObjects();
    this->_createFirstObject();
}
void GfxMgr::_createInstance()
{
    if (!this->_checkValidationLayerSupport())
    {
        throw std::runtime_error("Validation layers requested, but not available!");
    }
    // 程序信息
    VkApplicationInfo appInfo = {};
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    appInfo.pApplicationName = "Vulkan Engine";
    appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.pEngineName = "No Engine";
    appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
    appInfo.apiVersion = VK_API_VERSION_1_0;
    std::cout << "VkApplicationInfo..." << std::endl;

    // 实例信息
    VkInstanceCreateInfo createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    createInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; // 关键！

    createInfo.pApplicationInfo = &appInfo;
    std::cout << "VkInstanceCreateInfo..." << std::endl;

    auto extensions = this->_getRequiredExtensions();
    createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
    createInfo.ppEnabledExtensionNames = extensions.data();
    createInfo.enabledLayerCount = 0;
    createInfo.pNext = nullptr;

    if (enableValidationLayers)
    {
        VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
        createInfo.enabledLayerCount = static_cast<uint32_t>(ValidationLayers.size());
        createInfo.ppEnabledLayerNames = ValidationLayers.data();

        this->_populateDebugMessengerCreateInfo(debugCreateInfo);
        createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo;
    }

    if (vkCreateInstance(&createInfo, nullptr, &this->_vkinstance) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to create instance!");
    }
    std::cout << "VkInstance  Success..." << std::endl;
}
bool GfxMgr::_checkValidationLayerSupport()
{
    uint32_t layerCount;
    vkEnumerateInstanceLayerProperties(&layerCount, nullptr);

    std::vector<VkLayerProperties> availableLayers(layerCount);
    vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
    for (const char *layerName : ValidationLayers)
    {
        bool layerFound = false;

        for (const auto &layerProperties : availableLayers)
        {
            if (strcmp(layerName, layerProperties.layerName) == 0)
            {
                layerFound = true;
                break;
            }
        }

        if (!layerFound)
        {
            return false;
        }
    }
    return true;
}
// 消息回调 创建一个getRequiredExtensions函数，这个函数根据是否启用校验层，返回所需的扩展列表
std::vector<const char *> GfxMgr::_getRequiredExtensions()
{
    uint32_t glfwExtensionCount = 0;
    const char **glfwExtensions;
    glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);

    std::vector<const char *> extensions(glfwExtensions,
                                         glfwExtensions + glfwExtensionCount);
    if (enableValidationLayers)
    {
        extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); // 添加调试扩展
    }
    extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
    extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
    extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);

    return extensions;
}

void GfxMgr::_setupDebugMessenger()
{
    if (!enableValidationLayers)
    {
        return;
    }

    VkDebugUtilsMessengerCreateInfoEXT createInfo;
    this->_populateDebugMessengerCreateInfo(createInfo);

    if (this->_createDebugUtilsMessengerEXT(this->_vkinstance, &createInfo, nullptr, &this->_debugMessenger) != VK_SUCCESS)
    {
        throw std::runtime_error("failed to set up debug messenger!");
    }
}
void GfxMgr::_populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
{
    createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
    createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
    createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
    createInfo.pfnUserCallback = this->debugCallback;
}

// 使用vkGetInstanceProcAddr获取某个api的函数指针
VkResult GfxMgr::_createDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger)
{
    auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT");
    if (func != nullptr)
    {
        return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
    }
    else
    {
        return VK_ERROR_EXTENSION_NOT_PRESENT;
    }
}

void GfxMgr::_createSurface()
{
    if (glfwCreateWindowSurface(this->_vkinstance, WindowMgr::getInstance()->getWindow(), nullptr, &this->_surface) != VK_SUCCESS)
    {
        throw std::runtime_error("failed to create window surface!");
    }
}

void GfxMgr::_initPhysicalDevice()
{
    this->_physicalDevice = VK_NULL_HANDLE;
    uint32_t deviceCount = 0;
    vkEnumeratePhysicalDevices(this->_vkinstance, &deviceCount, nullptr); // 第三个参数为空，则表示该函数为读取功能
    if (deviceCount == 0)
    {
        throw std::runtime_error("Failed to find GPU with Vulkan Supported.");
    }
    std::cout << "Physical Device Count: " << deviceCount << std::endl;
    std::vector<VkPhysicalDevice> devices(deviceCount);
    vkEnumeratePhysicalDevices(this->_vkinstance, &deviceCount, devices.data());

    for (const auto &device : devices)
    {
        if (this->_isDeviceSuitable(device))
        {
            this->_physicalDevice = device;
            break;
        }
    }
    std::cout << "Physical Device: " << this->_physicalDevice << std::endl;
    // std::cout << "Physical Device: " << devices << std::endl;
    if (this->_physicalDevice == VK_NULL_HANDLE)
    {
        throw std::runtime_error("Failed to find a suitable a GPU.");
    }

    VkPhysicalDeviceProperties deviceProperties;
    vkGetPhysicalDeviceProperties(this->_physicalDevice, &deviceProperties);

    VkPhysicalDeviceLimits limits = deviceProperties.limits;

    // std::cout << "=== 物理设备图像限制 ===" << std::endl;
    // std::cout << "最大 1D 图像尺寸: " << limits.maxImageDimension1D << std::endl;
    // std::cout << "最大 2D 图像尺寸: " << limits.maxImageDimension2D << std::endl;
    // std::cout << "最大 3D 图像尺寸: " << limits.maxImageDimension3D << std::endl;
    // std::cout << "最大立方体贴图尺寸: " << limits.maxImageDimensionCube << std::endl;
    // std::cout << "最大图像数组层数: " << limits.maxImageArrayLayers << std::endl;
    // std::cout << "最大帧缓冲颜色附件数: " << limits.maxColorAttachments << std::endl;

    // // 纹理采样器限制
    // std::cout << "最大各向异性过滤: " << limits.maxSamplerAnisotropy << std::endl;
    // std::cout << "最大采样器LOD偏差: " << limits.maxSamplerLodBias << std::endl;
}
bool GfxMgr::_isDeviceSuitable(VkPhysicalDevice device)
{
    VkPhysicalDeviceProperties deviceProperties;
    vkGetPhysicalDeviceProperties(device, &deviceProperties);

    // 纹理压缩、64为浮点、多窗口渲染是否支持，通过下面函数查询
    VkPhysicalDeviceFeatures deviceFeatures;
    vkGetPhysicalDeviceFeatures(device, &deviceFeatures);

    // 显卡支持集合着色器的判断条件
    bool isSupportSetShader = (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) && deviceFeatures.geometryShader;
    std::cout << "isSupportSetShader: " << isSupportSetShader << std::endl;

    QueueFamilyIndices indices = this->findQueueFamilies(device);
    // 由于我们只需要显示三角形，所以不需要额外特性，直接返回true即可，以上代码作为测试
    bool extensionsSupported = this->_checkDeviceExtensionSupport(device);

    bool swapChainAdequate = false;
    if (extensionsSupported)
    {
        SwapChainSupportDetails swapChainSupport = this->querySwapChainSupport(device);
        swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty();
    }

    return indices.isComplete() && extensionsSupported && swapChainAdequate;
}

bool GfxMgr::_checkDeviceExtensionSupport(VkPhysicalDevice device)
{
    uint32_t extensionCount;
    vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr);

    std::vector<VkExtensionProperties> availableExtensions(extensionCount);
    vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data());

    std::set<std::string> requiredExtensions(DeviceExtensions.begin(), DeviceExtensions.end());

    for (auto extension : DeviceExtensions)
    {
        std::cout << "extension: " << extension << std::endl;
    }

    for (const auto &extension : availableExtensions)
    {
        requiredExtensions.erase(extension.extensionName);
    }

    return requiredExtensions.empty();
}

void GfxMgr::_createLogicalDevice()
{
    QueueFamilyIndices indices = this->findQueueFamilies(this->_physicalDevice);
    std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
    std::set<uint32_t> uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily};
    float queuePriority = 1.0f;
    std::cout << "uniqueQueueFamilies: " << uniqueQueueFamilies.size() << std::endl;
    for (uint32_t queueFamily : uniqueQueueFamilies)
    {
        VkDeviceQueueCreateInfo queueCreateInfo{};
        queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
        queueCreateInfo.queueFamilyIndex = queueFamily;
        queueCreateInfo.queueCount = 1;
        queueCreateInfo.pQueuePriorities = &queuePriority;
        queueCreateInfos.push_back(queueCreateInfo);
    }
    // 指定应用程序使用的设备特性
    VkPhysicalDeviceFeatures deviceFeatures = {};
    deviceFeatures.geometryShader = VK_FALSE;
    deviceFeatures.tessellationShader = VK_FALSE; // 例如禁用曲面细分

    // 创建逻辑设备
    VkDeviceCreateInfo createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    createInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());
    createInfo.pQueueCreateInfos = queueCreateInfos.data();
    createInfo.pEnabledFeatures = &deviceFeatures;

    // For macos
    std::vector<const char *> localDeviceExtensions = DeviceExtensions;
    uint32_t extensionCount;
    vkEnumerateDeviceExtensionProperties(this->_physicalDevice, nullptr, &extensionCount, nullptr);
    std::vector<VkExtensionProperties> availableExtensions(extensionCount);
    vkEnumerateDeviceExtensionProperties(this->_physicalDevice, nullptr, &extensionCount, availableExtensions.data());
    for (const auto &extension : availableExtensions)
    {
        if (strcmp(extension.extensionName, "VK_KHR_portability_subset") == 0)
        {
            localDeviceExtensions.push_back("VK_KHR_portability_subset");
            break;
        }
    }
    createInfo.enabledExtensionCount = static_cast<uint32_t>(localDeviceExtensions.size());
    createInfo.ppEnabledExtensionNames = localDeviceExtensions.data();

    if (enableValidationLayers)
    {
        createInfo.enabledLayerCount = static_cast<uint32_t>(ValidationLayers.size());
        createInfo.ppEnabledLayerNames = ValidationLayers.data();
    }
    else
    {
        createInfo.enabledLayerCount = 0;
    }

    if (vkCreateDevice(this->_physicalDevice, &createInfo, nullptr, &this->_vkdevice) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to create logical device!");
    }

    std::cout << "create logical device success" << std::endl;
    vkGetDeviceQueue(this->_vkdevice, indices.graphicsFamily, 0, &this->_graphicsQueue);
    vkGetDeviceQueue(this->_vkdevice, indices.presentFamily, 0, &this->_presentQueue);
}
VkDevice GfxMgr::getVulkanDevice()
{
    return this->_vkdevice;
}

VkQueue GfxMgr::getPresentQueue()
{
    return this->_presentQueue;
}
VkQueue GfxMgr::getGraphicsQueue()
{
    return this->_graphicsQueue;
}

/**
 * @brief 创建交换链
 *
 */
void GfxMgr::_createSwapChain()
{
    std::cout << "create swap chain start..." << std::endl;
    SwapChainSupportDetails swapChainSupport = this->querySwapChainSupport(this->_physicalDevice);

    VkSurfaceFormatKHR surfaceFormat = this->_chooseSwapSurfaceFormat(swapChainSupport.formats);
    VkPresentModeKHR presentMode = this->_chooseSwapPresentMode(swapChainSupport.presentModes);
    VkExtent2D extent = this->_chooseSwapExtent(swapChainSupport.capabilities);

    uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
    if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount)
    {
        imageCount = swapChainSupport.capabilities.maxImageCount;
    }

    VkSwapchainCreateInfoKHR createInfo = {};
    createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    createInfo.surface = this->_surface;
    createInfo.minImageCount = imageCount;
    createInfo.imageFormat = surfaceFormat.format;
    createInfo.imageColorSpace = surfaceFormat.colorSpace;
    createInfo.imageExtent = extent;
    createInfo.imageArrayLayers = 1;                             // 用于指定每个图像所包含的层次。除了VR场景外，一般都是1.
    createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; // 指定我们在图像上的操作，此处我们将图像作为颜色来使用
    createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
    /**
     * VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
     * VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR
     * VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
     */

    QueueFamilyIndices indices = this->findQueueFamilies(this->_physicalDevice);
    uint32_t queueFamilyIndices[] = {(uint32_t)indices.graphicsFamily, (uint32_t)indices.presentFamily};

    if (indices.graphicsFamily != indices.presentFamily)
    {
        createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
        createInfo.queueFamilyIndexCount = 2;
        createInfo.pQueueFamilyIndices = queueFamilyIndices;
    }
    else
    {
        createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
        createInfo.queueFamilyIndexCount = 0;     // Optional
        createInfo.pQueueFamilyIndices = nullptr; // Optional
    }

    createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
    createInfo.presentMode = presentMode;
    createInfo.clipped = VK_TRUE;

    createInfo.oldSwapchain = VK_NULL_HANDLE;

    if (vkCreateSwapchainKHR(this->_vkdevice, &createInfo, nullptr, &this->_swapChain) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to create swap chain!");
    }

    std::cout << "create swap chain success..." << std::endl;

    // 用vkGetSwapchainImagesKHR查询最终的图像数量
    vkGetSwapchainImagesKHR(this->_vkdevice, this->_swapChain, &imageCount, nullptr);
    // 创建交换链图像数组
    this->_swapChainImages.resize(imageCount);
    vkGetSwapchainImagesKHR(this->_vkdevice, this->_swapChain, &imageCount, this->_swapChainImages.data());
    // 同时还需要将这个格式和分辨率保存下来。
    this->_swapChainImageFormat = surfaceFormat.format;
    this->_swapChainExtent = extent;
}
VkFormat GfxMgr::getSwapChainImageFormat()
{
    return this->_swapChainImageFormat;
}

VkExtent2D GfxMgr::getSwapChainExtent()
{
    return this->_swapChainExtent;
}

// https://www.iogl.cn/tutorial/swapchain
VkSurfaceFormatKHR GfxMgr::_chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR> &availableFormats)
{
    // 优先选择 B8G8R8A8_UNORM + SRGB
    for (const auto &availableFormat : availableFormats)
    {
        if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
        {
            return availableFormat;
        }
    }
    // 次优选择：任何带 Alpha 的格式
    for (const auto &format : availableFormats)
    {
        if (format.format == VK_FORMAT_B8G8R8A8_UNORM ||
            format.format == VK_FORMAT_R8G8B8A8_UNORM)
        {
            return format;
        }
    }

    return availableFormats[0];
}
// https://www.iogl.cn/tutorial/swapchain
VkPresentModeKHR GfxMgr::_chooseSwapPresentMode(const std::vector<VkPresentModeKHR> &availablePresentModes)
{
    for (const auto &availablePresentMode : availablePresentModes)
    {
        if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR)
        {
            return availablePresentMode;
        }
    }

    return VK_PRESENT_MODE_FIFO_KHR;
}
VkExtent2D GfxMgr::_chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities)
{
    if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max())
    {
        return capabilities.currentExtent;
    }
    else
    {
        int width, height;
        glfwGetFramebufferSize(WindowMgr::getInstance()->getWindow(), &width, &height);

        VkExtent2D actualExtent = {
            static_cast<uint32_t>(width),
            static_cast<uint32_t>(height)};

        actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
        actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);

        return actualExtent;
    }
}
/**
 * @brief 创建交换链图像视图
 *
 */
void GfxMgr::_createImageViews()
{
    std::cout << "create ImageViews start..." << std::endl;
    this->_swapChainImageViews.resize(this->_swapChainImages.size());
    for (size_t i = 0; i < this->_swapChainImages.size(); i++)
    {
        VkImageViewCreateInfo createInfo = {};
        createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        createInfo.image = this->_swapChainImages[i];
        createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        createInfo.format = this->_swapChainImageFormat;
        createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        createInfo.subresourceRange.baseMipLevel = 0;
        createInfo.subresourceRange.levelCount = 1;
        createInfo.subresourceRange.baseArrayLayer = 0;
        createInfo.subresourceRange.layerCount = 1;
        if (vkCreateImageView(this->_vkdevice, &createInfo, nullptr, &this->_swapChainImageViews[i]) != VK_SUCCESS)
        {
            throw std::runtime_error("failed to create image views!");
        }
    }
    std::cout << "create ImageViews success..." << std::endl;
}

/*
 * @brief 创建命令池
 */
void GfxMgr::_createCommandPool()
{

    std::cout << "create command pool start..." << std::endl;
    QueueFamilyIndices queueFamilyIndices = this->findQueueFamilies(this->_physicalDevice);

    VkCommandPoolCreateInfo poolInfo{};
    poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
    // 每个命令池只能分配在单一类型队列上提交的Command Buffer。我们将记录绘图命令，这就是我们选择图形队列系列的原因。
    poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily;

    // 创建Command Pool
    if (vkCreateCommandPool(this->_vkdevice, &poolInfo, nullptr, &this->_commandPool) != VK_SUCCESS)
    {
        throw std::runtime_error("failed to create command pool!");
    }
    std::cout << "create command pool success..." << std::endl;
}
VkCommandPool GfxMgr::getCommandPool()
{
    return this->_commandPool;
}
void GfxMgr::_createDescriptorPool()
{
    std::array<VkDescriptorPoolSize, 2> poolSizes{};
    poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
    poolSizes[0].descriptorCount = MAX_FRAMES_IN_FLIGHT * 100; // 支持更多
    poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
    poolSizes[1].descriptorCount = MAX_FRAMES_IN_FLIGHT * 100; // 支持更多

    VkDescriptorPoolCreateInfo poolInfo{};
    poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    poolInfo.poolSizeCount = static_cast<uint32_t>(poolSizes.size());
    poolInfo.pPoolSizes = poolSizes.data();
    poolInfo.maxSets = MAX_FRAMES_IN_FLIGHT * 100; // 支持更多描述符集

    if (vkCreateDescriptorPool(_vkdevice, &poolInfo, nullptr, &_descriptorPool) != VK_SUCCESS)
    {
        throw std::runtime_error("failed to create descriptor pool!");
    }
    std::cout << "create descriptor pool success..." << std::endl;

    // //需要销毁
    // if (this->_descriptorPool != VK_NULL_HANDLE) {
    //     vkDestroyDescriptorPool(this->_vkdevice, this->_descriptorPool, nullptr);
    //     this->_descriptorPool = VK_NULL_HANDLE;
    // }
}
VkDescriptorPool GfxMgr::getDescriptorPool()
{
    return this->_descriptorPool;
}

void GfxMgr::_createSyncObjects()
{
    std::cout << "create sync objects start..." << std::endl;
    size_t imageCount = this->_swapChainImages.size(); // 使用交换链图像数量
    this->_imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
    this->_renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
    this->_inFlightFences.resize(MAX_FRAMES_IN_FLIGHT);
    this->_imagesInFlight.resize(imageCount, VK_NULL_HANDLE);

    VkSemaphoreCreateInfo semaphoreInfo{};
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;

    VkFenceCreateInfo fenceInfo{};
    fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
    fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;

    for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++)
    {
        vkCreateSemaphore(this->_vkdevice, &semaphoreInfo, nullptr, &this->_imageAvailableSemaphores[i]);
        vkCreateSemaphore(this->_vkdevice, &semaphoreInfo, nullptr, &this->_renderFinishedSemaphores[i]);
        vkCreateFence(this->_vkdevice, &fenceInfo, nullptr, &this->_inFlightFences[i]);
    }
    std::cout << "create sync objects success..." << std::endl;
}

std::vector<VkImage> GfxMgr::getSwapChainImages()
{
    return this->_swapChainImages;
}

std::vector<VkImageView> GfxMgr::getSwapChainImageViews()
{
    return this->_swapChainImageViews;
}

void GfxMgr::_createFirstObject()
{
    std::cout << "create first object start..." << std::endl;

    this->_firstObject = new GfxObject(GfxObjectTypeE::DEFAULT);

    std::vector<float> positions = {
        -1.0f, 1.0f, 0.0f, 0.0f,
        -1.0f, -1.0f, 0.0f, 0.0f,
        1.0f, -1.0f, 0.0f, 0.0f,
        1.0f, 1.0f, 1.0f, 0.0f};
    std::vector<float> colors = {
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
    };
    std::vector<float> normals = {
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f,
        0.0f};
    std::vector<float> uvs = {
        0.0f,
        0.0f,
        0.0f,
        1.0f,
        1.0f,
        1.0f,
        1.0f,
        0.0f,
    };
    std::vector<uint32_t> indices = {
        0, 1, 2,
        0, 2, 3};
    this->_firstObject->setVertexs(positions, colors, normals, uvs, indices);

    this->_firstObject->setClear(true);
    this->_firstObject->setColor(0.0f, 0.0f, 0.0f, 0.0f);

    std::string path = "resources/ui/ic-default.png";
    if (this->_textures.find(path) == this->_textures.end())
    {
        this->_textures[path] = new GfxTexture(path);
    }
    this->_firstObject->setTexture(this->_textures[path]);

    // 统一管理shader
    std::string shaderPath = "resources/effects/default/default";
    if (this->_shaders.find(shaderPath) == this->_shaders.end())
    {
        this->_shaders[shaderPath] = new GfxShader(shaderPath);
    }
    // 统一管理pass
    if (this->_passes.find("DEFAULT_PASS") == this->_passes.end())
    {
        this->_passes["DEFAULT_PASS"] = new GfxPass(GfxObjectTypeE::DEFAULT, "DEFAULT_PASS");
    }
    // 通过shader 和 pass 检索对应的pipeline
    std::string pipelineKey = std::string("DEFAULT_PASS") + "_" + shaderPath;
    if (this->_pipelines.find(pipelineKey) == this->_pipelines.end())
    {
        this->_pipelines[pipelineKey] = new GfxPipeline(GfxObjectTypeE::DEFAULT, this->_shaders[shaderPath], this->_passes["DEFAULT_PASS"]);
    }
    std::cout << "create first object success..." << std::endl;

    this->_firstObject->setPipeline(this->_pipelines[pipelineKey]);
}
void GfxMgr::createGfxTexture(std::string textureUuid, const void *pixels, int width, int height, int channels, int imageSize)
{
    if (this->_textures.find(textureUuid) == this->_textures.end())
    {
        this->_textures[textureUuid] = new GfxTexture(textureUuid, pixels, width, height, channels, imageSize);
    }
}
void GfxMgr::destroyGfxTexture(std::string textureUuid)
{
    if (this->_textures.find(textureUuid) != this->_textures.end())
    {
        delete this->_textures[textureUuid];
        this->_textures.erase(textureUuid);
    }
}

/**
 * @brief 添加UI对象
 *
 * @param id
 */
void GfxMgr::addUIObject(std::string id)
{
    std::cout << "add ui object " << id << std::endl;

    GfxObject *object = new GfxObject(GfxObjectTypeE::UI);
    this->_uiObjects[id] = object;
}
void GfxMgr::updateUIObjectShader(std::string id, std::string shaderPath)
{
    std::cout << "update ui object shader " << id << " " << shaderPath << std::endl;
    // 统一管理shader
    // std::string shaderPath = "resources/effects/default/default";
    if (this->_shaders.find(shaderPath) == this->_shaders.end())
    {
        this->_shaders[shaderPath] = new GfxShader(shaderPath);
    }
    // 统一管理pass
    if (this->_passes.find("DEFAULT_PASS") == this->_passes.end())
    {
        this->_passes["DEFAULT_PASS"] = new GfxPass(GfxObjectTypeE::DEFAULT, "DEFAULT_PASS");
    }
    // 通过shader 和 pass 检索对应的pipeline
    std::string pipelineKey = std::string("DEFAULT_PASS") + "_" + shaderPath;
    if (this->_pipelines.find(pipelineKey) == this->_pipelines.end())
    {
        this->_pipelines[pipelineKey] = new GfxPipeline(GfxObjectTypeE::DEFAULT, this->_shaders[shaderPath], this->_passes["DEFAULT_PASS"]);
    }
    this->_uiObjects[id]->setPipeline(this->_pipelines[pipelineKey]);
}
void GfxMgr::updateUIObjectVertexs(std::string id, std::vector<float> points, std::vector<float> colors, std::vector<float> normals, std::vector<float> uvs, std::vector<uint32_t> indices)
{
    std::cout << "update ui object vertexs " << id << std::endl;

    this->_uiObjects[id]->setVertexs(points, colors, normals, uvs, indices);
}
void GfxMgr::updateUIObjectColor(std::string id, float r, float g, float b, float a)
{
    std::cout << "update ui object color " << id << " " << r << " " << g << " " << b << " " << a << std::endl;
    this->_uiObjects[id]->setColor(r, g, b, a);
}
void GfxMgr::updateUIObjectTexture(std::string id, std::string path)
{
    if (this->_textures.find(path) == this->_textures.end())
    {
        this->_textures[path] = new GfxTexture(path);
    }
    this->_uiObjects[id]->setTexture(this->_textures[path]);
}

void GfxMgr::update(std::vector<std::string> &renderers)
{

    // std::cout << "update1" << this->_inFlightFences[this->_currentFrame] << std::endl;
    // 阻塞CPU，直到 GPU 完成 上一帧 的所有渲染任务（即关联到这个栅栏的命令全部执行完毕）。
    // 相当于对 GPU 说："你先把上一帧的活干完，我再给你新任务"。
    // 防止 CPU 过快提交新帧，导致 GPU 还在处理旧帧时，资源被意外覆盖（比如命令缓冲区被重用）
    // 确保交换链图像、Uniform 缓冲区等不会被同时读写。
    vkWaitForFences(this->_vkdevice, 1, &this->_inFlightFences[this->_currentFrame], VK_TRUE, UINT64_MAX);
    // 重置任务完成标志
    // 将栅栏的状态从 "已触发"（ signaled） 重置为 "未触发"（unsignaled）。
    // 相当于把 "任务完成" 的标志牌翻回 "未完成" 状态。
    vkResetFences(this->_vkdevice, 1, &this->_inFlightFences[this->_currentFrame]);
    // 上边等待的实际上是上一轮同位置帧的栅栏
    /**
     * _inFlightFences[_currentFrame]：
     * 标记 当前CPU帧 的GPU任务状态（等待的是 上一轮同位置的帧）。
     * _imageAvailableSemaphores[_currentFrame]：
     * 为 当前CPU帧 绑定一个新的图像获取信号量。
     */
    // 可用的图像的索引
    uint32_t imageIndex;
    /**
     * 从交换链申请一个可渲染的图像
     * 通过 _imageAvailableSemaphores[_currentFrame] 信号量，通知 GPU："必须等这个信号量触发后，才能开始渲染该图像"。
     */
    VkResult result1 = vkAcquireNextImageKHR(this->_vkdevice, this->_swapChain, UINT64_MAX, this->_imageAvailableSemaphores[this->_currentFrame], VK_NULL_HANDLE, &imageIndex);
    // 如果交换链已过期（如窗口大小改变），会返回 VK_ERROR_OUT_OF_DATE_KHR，触发重建交换链
    if (result1 == VK_ERROR_OUT_OF_DATE_KHR || result1 == VK_SUBOPTIMAL_KHR)
    {
        std::cout << "renderer update:'VK_ERROR_OUT_OF_DATE_KHR',The window size might have changed, and the swap chain needs to be recreated." << std::endl;
        this->_resetSwapChain();
        return;
    }
    /**
     * 检查当前获取索引图像是否已被其他帧使用
     */
    long time = Time::nowTime();
    if (this->_imagesInFlight[imageIndex] != VK_NULL_HANDLE)
    {
        // 先检查状态避免不必要等待
        if (vkGetFenceStatus(this->_vkdevice, this->_imagesInFlight[imageIndex]) == VK_NOT_READY)
        {
            /**
             * VK_NOT_READY:栅栏未触发，GPU仍在处理关联的操作
             * VK_SUCCESS:栅栏已触发，关联的GPU操作已完成，可以安全复用图像
             */
            std::cout << "renderer update:'VK_ERROR_OUT_OF_DATE_KHR',The image is being used by other frames and needs to wait." << std::endl;
            vkWaitForFences(this->_vkdevice, 1, &this->_imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
        }
    }
    // std::cout << "renderer update:'VK_ERROR_OUT_OF_DATE_KHR',wait time: " << Time::nowTime() - time << std::endl;

    // 占用结束后重新编辑，将当前帧的栅栏与图像绑定，表示 该图像现在由当前帧使用。
    this->_imagesInFlight[imageIndex] = this->_inFlightFences[this->_currentFrame];

    // 准备渲染buffer
    std::vector<VkCommandBuffer> commandBuffers;
    // // 第一个默认渲染物
    this->_firstObject->updateRender(imageIndex);
    commandBuffers.push_back(this->_firstObject->getCommandBuffer(imageIndex));

    for (auto &rendererId : renderers)
    {
        if (this->_uiObjects.find(rendererId) == this->_uiObjects.end())
        {
            continue;
        }
        this->_uiObjects[rendererId]->updateRender(imageIndex);
        commandBuffers.push_back(this->_uiObjects[rendererId]->getCommandBuffer(imageIndex));
    }

    // 渲染当前帧
    // 等待信号量配置（图像可用时触发） vkAcquireNextImageKHR 处理的
    VkSemaphore waitSemaphores[] = {this->_imageAvailableSemaphores[this->_currentFrame]};
    // 指定 GPU 在哪个流水线阶段等待信号量。COLOR_ATTACHMENT_OUTPUT_BIT：确保在颜色附件写入阶段之前等待（避免图像未就绪时开始渲染）。
    VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};

    // 完成渲染后触发的信号量 表示渲染已完成（用于通知 vkQueuePresentKHR 可以显示图像）。
    VkSemaphore signalSemaphores[] = {this->_renderFinishedSemaphores[this->_currentFrame]};
    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.waitSemaphoreCount = 1;
    submitInfo.pWaitSemaphores = waitSemaphores;
    submitInfo.pWaitDstStageMask = waitStages;
    submitInfo.commandBufferCount = static_cast<uint32_t>(commandBuffers.size());
    submitInfo.pCommandBuffers = commandBuffers.data();
    submitInfo.signalSemaphoreCount = 1;

    submitInfo.pSignalSemaphores = signalSemaphores;

    if (vkQueueSubmit(this->_graphicsQueue, 1, &submitInfo, this->_inFlightFences[this->_currentFrame]) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to submit draw command buffer!");
    }
    // 显示当前帧，将当前帧的图像呈现在屏幕上
    VkSwapchainKHR swapChains[] = {this->_swapChain};
    VkPresentInfoKHR presentInfo{};
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.waitSemaphoreCount = 1;
    presentInfo.pWaitSemaphores = signalSemaphores;
    presentInfo.swapchainCount = 1;
    presentInfo.pSwapchains = swapChains;
    presentInfo.pImageIndices = &imageIndex;
    VkResult result2 = vkQueuePresentKHR(this->_presentQueue, &presentInfo);
    // 如果返回 VK_ERROR_OUT_OF_DATE_KHR 或 VK_SUBOPTIMAL_KHR，需要重新创建交换链（例如窗口大小改变后）
    if (result2 == VK_ERROR_OUT_OF_DATE_KHR || result2 == VK_SUBOPTIMAL_KHR)
    {
        this->_resetSwapChain();
        return;
    }
    else if (result2 != VK_SUCCESS)
    {
        std::cout << "Failed to present swap chain imag22222e!" << std::endl;
    }
    // 0 1 0 1 0 1
    /**
     * 帧0	提交命令，信号量A	开始渲染帧0
     * 帧1	提交命令，信号量B	渲染帧0完成，开始渲染帧1
     * 帧0	等待帧0栅栏，信号量A复用	渲染帧1完成，显示帧0
     */
    this->_currentFrame = (this->_currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
    this->_frameCount++;
}

void GfxMgr::_resetSwapChain()
{
    std::cout << "reset swap chain start ................" << std::endl;
    // 交换链（Swapchain） 核心对象，存储渲染目标图像。
    // 交换链图像视图（Image Views） 直接绑定到交换链图像，旧视图会失效。
    // 帧缓冲（Framebuffers） 引用交换链图像视图和深度缓冲，必须匹配新的图像。
    // 深度缓冲（Depth Buffer） 如果交换链尺寸改变，深度缓冲的分辨率需同步更新。
    // 渲染通道（Render Pass） 如果交换链格式（如 VK_FORMAT_B8G8R8A8_UNORM）改变，可能需要调整附件描述。
    // 图形管线（Graphics Pipeline） 如果视口（Viewport）或裁剪矩形（Scissor）依赖交换链尺寸，需重新创建。
    vkDeviceWaitIdle(_vkdevice); // 等待所有操作完成

    // 倒着从后往前清理
    // 清除所有object的_swapChainFramebuffers和_commandBuffers
    this->_firstObject->clear();
    for (auto &[name, object] : this->_uiObjects)
    {
        object->clear();
    }
    // 1. 销毁旧的同步对象
    for (auto &fence : this->_inFlightFences)
    {
        vkDestroyFence(this->_vkdevice, fence, nullptr);
    }
    // 1. 销毁旧的同步对象
    for (auto &flight : this->_imagesInFlight)
    {
        vkDestroyFence(this->_vkdevice, flight, nullptr);
    }
    for (auto &semaphore : this->_imageAvailableSemaphores)
    {
        vkDestroySemaphore(this->_vkdevice, semaphore, nullptr);
    }
    for (auto &semaphore : this->_renderFinishedSemaphores)
    {
        vkDestroySemaphore(this->_vkdevice, semaphore, nullptr);
    }
    std::fill(_imagesInFlight.begin(), _imagesInFlight.end(), VK_NULL_HANDLE);
    // 清空图形管线（Pipeline）
    for (auto &[name, pipeline] : this->_pipelines)
    {
        pipeline->clear();
    }
    // 清空渲染通道（Render Pass）
    for (auto &[name, renderPass] : this->_passes)
    {
        renderPass->clear();
    }
    // 销毁交换链图像视图（Image Views）
    for (auto imageView : this->_swapChainImageViews)
    {
        vkDestroyImageView(this->_vkdevice, imageView, nullptr);
    }
    this->_swapChainImageViews.clear();

    // 销毁交换链（Swapchain）
    if (this->_swapChain != VK_NULL_HANDLE)
    {
        vkDestroySwapchainKHR(this->_vkdevice, this->_swapChain, nullptr);
        this->_swapChain = VK_NULL_HANDLE;
    }
    // 从前往后重新创建
    this->_createSwapChain();
    // 交换链
    this->_createImageViews();

    // 图像视图
    // _createDepthResources();     // 深度缓冲
    // 重置渲染通道
    for (auto &[name, renderPass] : this->_passes)
    {
        renderPass->reset();
    }
    // 重置管线
    for (auto &[name, pipeline] : this->_pipelines)
    {
        pipeline->reset();
    }

    this->_createSyncObjects();
    // 重置物品
    this->_firstObject->reset();
    for (auto &[name, object] : this->_uiObjects)
    {
        object->reset();
    }
    std::cout << "reset swap chain end ................" << std::endl;
}

SwapChainSupportDetails GfxMgr::querySwapChainSupport(VkPhysicalDevice device)
{
    SwapChainSupportDetails details;

    // 与交换链相关的函数都需要device和surface这两个参数
    // 查询基础表面特性
    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, this->_surface, &details.capabilities);

    // 查询表面支持格式
    uint32_t formatCount;
    vkGetPhysicalDeviceSurfaceFormatsKHR(device, this->_surface, &formatCount, nullptr);
    if (formatCount != 0)
    {
        details.formats.resize(formatCount);
        vkGetPhysicalDeviceSurfaceFormatsKHR(device, this->_surface, &formatCount, details.formats.data());
    }

    // 查询表面支持呈现模式
    uint32_t presentModeCount;
    vkGetPhysicalDeviceSurfacePresentModesKHR(device, this->_surface, &presentModeCount, nullptr);

    if (presentModeCount != 0)
    {
        details.presentModes.resize(presentModeCount);
        vkGetPhysicalDeviceSurfacePresentModesKHR(device, this->_surface, &presentModeCount, details.presentModes.data());
    }

    return details;
}

QueueFamilyIndices GfxMgr::findQueueFamilies(VkPhysicalDevice device)
{
    QueueFamilyIndices indices;

    uint32_t queueFamilyCount = 0;
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
    std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
    vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());

    int index = 0;
    for (const auto &queueFamily : queueFamilies)
    {
        if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT)
        { // 目前，我们只要寻找图形队列即可
            indices.graphicsFamily = index;
        }

        VkBool32 presentSupport = false;
        vkGetPhysicalDeviceSurfaceSupportKHR(device, index, this->_surface, &presentSupport);
        if (presentSupport)
        {
            indices.presentFamily = index;
        }

        if (indices.isComplete())
        {
            break;
        }
        index++;
    }

    return indices;
}

// 读取shader内容
std::vector<char> GfxMgr::readShaderFile(const std::string &filename)
{
    // ate: 表示从文件末未开始读取
    // binary: 表示以二进制方式读取
    std::ifstream file(filename, std::ios::ate | std::ios::binary);
    std::cout << filename << std::endl;
    if (!file.is_open())
    {
        throw std::runtime_error("failed to open file!");
    }
    // tellg()返回当前定位指针的位置，也代表着输入流的大小。
    size_t fileSize = (size_t)file.tellg();
    std::cout << fileSize << std::endl;
    std::vector<char> buffer(fileSize);
    // seekg()是对输入流的操作 g是get缩写，0是代表从开头读起。
    file.seekg(0);
    // 读入到Buffer当中
    file.read(buffer.data(), fileSize);
    file.close();
    std::cout << "read file success: " << filename << std::endl;
    return buffer;
}
// 要将着色器字节码在管线上使用，还需要使用VkShaderModule转换
VkShaderModule GfxMgr::createShaderModule(const std::vector<char> &code)
{
    VkShaderModuleCreateInfo createInfo{};
    createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
    createInfo.codeSize = code.size();
    createInfo.pCode = reinterpret_cast<const uint32_t *>(code.data());

    std::cout << "shader code size: " << code.size() << "\n";

    VkShaderModule shaderModule;
    if (vkCreateShaderModule(this->_vkdevice, &createInfo, nullptr, &shaderModule) != VK_SUCCESS)
    {
        throw std::runtime_error("Failed to create shader module!");
    }

    return shaderModule;
}

VkResult GfxMgr::createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkBuffer *buffer, VkDeviceMemory *memory, VkDeviceSize size, void *data = nullptr)
{
    VkBufferCreateInfo bufferCreateInfo{};
    bufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
    bufferCreateInfo.usage = usageFlags;
    bufferCreateInfo.size = size;
    bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    vkCreateBuffer(this->_vkdevice, &bufferCreateInfo, nullptr, buffer);

    VkMemoryRequirements memReqs;
    VkMemoryAllocateInfo memAlloc{};
    memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
    vkGetBufferMemoryRequirements(this->_vkdevice, *buffer, &memReqs);
    memAlloc.allocationSize = memReqs.size;
    memAlloc.memoryTypeIndex = getMemoryTypeIndex(memReqs.memoryTypeBits, memoryPropertyFlags);
    vkAllocateMemory(this->_vkdevice, &memAlloc, nullptr, memory);

    if (data != nullptr)
    {
        void *mapped;
        vkMapMemory(this->_vkdevice, *memory, 0, size, 0, &mapped);
        memcpy(mapped, data, size);
        vkUnmapMemory(this->_vkdevice, *memory);
    }

    vkBindBufferMemory(this->_vkdevice, *buffer, *memory, 0);
    return VK_SUCCESS;
}
uint32_t GfxMgr::getMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties)
{
    VkPhysicalDeviceMemoryProperties deviceMemoryProperties;
    vkGetPhysicalDeviceMemoryProperties(this->_physicalDevice, &deviceMemoryProperties);
    for (uint32_t i = 0; i < deviceMemoryProperties.memoryTypeCount; i++)
    {
        if ((typeBits & 1) == 1)
        {
            if ((deviceMemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
            {
                return i;
            }
        }
        typeBits >>= 1;
    }
    return 0;
}
/**
 *
 */
void GfxMgr::transitionImageLayout(VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t mipLevels)
{

    VkCommandBuffer commandBuffer = this->_beginSingleTimeCommands();

    VkImageMemoryBarrier barrier{};
    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    barrier.oldLayout = oldLayout;
    barrier.newLayout = newLayout;
    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.image = image;

    // 设置子资源范围
    if (newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
    {
        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
        if (this->_hasStencilComponent(format))
        {
            barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
        }
    }
    else
    {
        barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    }

    barrier.subresourceRange.baseMipLevel = 0;
    barrier.subresourceRange.levelCount = mipLevels;
    barrier.subresourceRange.baseArrayLayer = 0;
    barrier.subresourceRange.layerCount = 1;

    // 设置管道阶段和访问掩码
    VkPipelineStageFlags sourceStage;
    VkPipelineStageFlags destinationStage;

    if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
    {
        barrier.srcAccessMask = 0;
        barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;

        sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
        destinationStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
    }
    else if (oldLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL && newLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
    {
        barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
        barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;

        sourceStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
        destinationStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
    }
    else if (oldLayout == VK_IMAGE_LAYOUT_UNDEFINED && newLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
    {
        barrier.srcAccessMask = 0;
        barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;

        sourceStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
        destinationStage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
    }
    else
    {
        throw std::invalid_argument("unsupported layout transition!");
    }

    vkCmdPipelineBarrier(commandBuffer, sourceStage, destinationStage, 0,
                         0, nullptr, 0, nullptr, 1, &barrier);

    this->_endSingleTimeCommands(commandBuffer);
}

VkCommandBuffer GfxMgr::_beginSingleTimeCommands()
{
    VkCommandBufferAllocateInfo allocInfo{};
    allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    allocInfo.commandPool = this->_commandPool;
    allocInfo.commandBufferCount = 1;

    VkCommandBuffer commandBuffer;
    vkAllocateCommandBuffers(this->_vkdevice, &allocInfo, &commandBuffer);

    VkCommandBufferBeginInfo beginInfo{};
    beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;

    vkBeginCommandBuffer(commandBuffer, &beginInfo);

    return commandBuffer;
}
void GfxMgr::_endSingleTimeCommands(VkCommandBuffer commandBuffer)
{
    vkEndCommandBuffer(commandBuffer);

    VkSubmitInfo submitInfo{};
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = &commandBuffer;

    vkQueueSubmit(this->_graphicsQueue, 1, &submitInfo, VK_NULL_HANDLE);
    vkQueueWaitIdle(this->_graphicsQueue);

    vkFreeCommandBuffers(this->_vkdevice, this->_commandPool, 1, &commandBuffer);
}
bool GfxMgr::_hasStencilComponent(VkFormat format)
{
    return format == VK_FORMAT_D32_SFLOAT_S8_UINT || format == VK_FORMAT_D24_UNORM_S8_UINT;
}
void GfxMgr::copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height)
{
    VkCommandBuffer commandBuffer = this->_beginSingleTimeCommands();

    VkBufferImageCopy region{};
    region.bufferOffset = 0;
    region.bufferRowLength = 0;
    region.bufferImageHeight = 0;

    region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
    region.imageSubresource.mipLevel = 0;
    region.imageSubresource.baseArrayLayer = 0;
    region.imageSubresource.layerCount = 1;

    region.imageOffset = {0, 0, 0};
    region.imageExtent = {width, height, 1};

    vkCmdCopyBufferToImage(commandBuffer, buffer, image,
                           VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);

    this->_endSingleTimeCommands(commandBuffer);
}

GfxMgr::~GfxMgr()
{
}

// this->_firstObject->updateRender(imageIndex);
// commandBuffersToSubmit.push_back(this->_firstObject->getCommandBuffer(imageIndex));

// for (const auto &name : this->_insertionOrder)
// {
//    if (this->_uiObjects[name])
//     {
//         this->_uiObjects[name]->updateRender();

//         VkCommandBuffer cmd = this->_uiObjects[name]->getCommandBuffer(imageIndex);
//         // // 2. 可选：更新物体的Uniform缓冲区
//         // // object->updateUniformBuffer(cameraView, cameraProj);
//         // // 3. 收集命令缓冲
//         commandBuffersToSubmit.push_back(cmd);
//     }
// }